package com.ihome.framework.core.tx.callback;

import java.util.concurrent.Callable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

import com.google.common.base.FinalizablePhantomReference;
import com.ihome.framework.core.log.Log;

public class IHomeTransactionThreadLocal {

	private static final Logger LOG = LoggerFactory.getLogger(IHomeTransactionThreadLocal.class);

	public static void registerAfterCommit(final Callable<?> callable, final Integer order) {
		Assert.notNull(callable);
		registerTransactionAdapter(new OrderTransactionSynchronizationAdapter(order) {

			@Override
			public void afterCommit() {
				try {
					callable.call();
				} catch (Exception e) {
					LOG.error(Log.op("pass").msg("call back error").toString(), e);
				}
			}
		});
	}

	public static void registerBeforeCommit(final Callable<?> callable, final Integer order) {
		Assert.notNull(callable);
		registerTransactionAdapter(new OrderTransactionSynchronizationAdapter(order) {

			@Override
			public void beforeCommit(boolean readOnly) {
				try {
					callable.call();
				} catch (Exception e) {
					LOG.error(Log.op("pass").msg("call back error").toString(), e);
				}
			}
		});
	}

	public static void registerBeforeCommit(final Callable<?> callable) {
		registerBeforeCommit(callable, null);
	}

	public static void registerAfterCommit(final Callable<?> callable) {
		registerAfterCommit(callable, null);
	}

	protected static void registerTransactionAdapter(TransactionSynchronizationAdapter adapter) {
		Assert.isTrue(TransactionSynchronizationManager.isActualTransactionActive()); // 验证事物开启
		TransactionSynchronizationManager.registerSynchronization(adapter);
	}

	@SuppressWarnings("unused")
	private static class OrderTransactionSynchronizationAdapter extends TransactionSynchronizationAdapter {

		private Integer order;

		public OrderTransactionSynchronizationAdapter(Integer order) {
			this.order = order;
		}

		@Override
		public int getOrder() {
			if (order == null) {
				return super.getOrder();
			} else {
				return order;
			}
		}

	}

}
